#include "stdafx.h"

using namespace System;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;

using namespace Gharen::GLCore;

namespace TestMath
{
	[TestClass]
	public ref class Vector3Tests
	{
	private:
		TestContext^ testContextInstance;

	public: 
		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		property Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ TestContext
		{
			Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ get()
			{
				return testContextInstance;
			}
			System::Void set(Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ value)
			{
				testContextInstance = value;
			}
		};

		#pragma region Additional test attributes
		//
		//You can use the following additional attributes as you write your tests:
		//
		//Use ClassInitialize to run code before running the first test in the class
		//[ClassInitialize()]
		//static void MyClassInitialize(TestContext^ testContext) {};
		//
		//Use ClassCleanup to run code after all tests in a class have run
		//[ClassCleanup()]
		//static void MyClassCleanup() {};
		//
		//Use TestInitialize to run code before running each test
		//[TestInitialize()]
		//void MyTestInitialize() {};
		//
		//Use TestCleanup to run code after each test has run
		//[TestCleanup()]
		//void MyTestCleanup() {};
		//
		#pragma endregion 

		bool AreEqual(float left, float right)
		{
			if(Math::Abs(left-right) < Single::Epsilon)
				return true;
			return false;
		}

		bool AreEqual(Vector3 left, glm::vec3 right)
		{
			return AreEqual(left.X, right.x) &&
					AreEqual(left.Y, right.y) &&
					AreEqual(left.Z, right.z);
		}

		[TestMethod]
		void Vector3Project()
		{
			Vector3 glCoreVector(42, 43, 333);
			glCoreVector = Vector3::Project(glCoreVector, Matrix::CreateLookAt(Vector3(10,10,22), Vector3(0,0,0), Vector3(0,1,0)),
				Matrix::CreateOrthographic(0, 500, 500, 0, -1, 100),
				Vector4(0,0, 1000, 1000));

			glm::vec3 glmVector(42, 43, 333);
			glmVector = glm::project(glmVector, glm::lookAt(glm::vec3(10,10,22), glm::vec3(0,0,0), glm::vec3(0,1,0)),
				glm::ortho(0.0f, 500.0f, 500.0f, 0.0f, -1.0f, 100.0f),
				glm::vec4(0,0,1000,1000));
			
			Assert::IsTrue(AreEqual(glCoreVector, glmVector));
		}

		[TestMethod]
		void Vector3Unproject()
		{
			Vector3 glCoreVector(42, 43, 333);
			glCoreVector = Vector3::Unproject(glCoreVector, Matrix::CreateLookAt(Vector3(10,10,22), Vector3(0,0,0), Vector3(0,1,0)),
				Matrix::CreateOrthographic(0, 500, 500, 0, -1, 100),
				Vector4(0,0, 1000, 1000));

			glm::vec3 glmVector(42, 43, 333);
			glmVector = glm::unProject(glmVector, glm::lookAt(glm::vec3(10,10,22), glm::vec3(0,0,0), glm::vec3(0,1,0)),
				glm::ortho(0.0f, 500.0f, 500.0f, 0.0f, -1.0f, 100.0f),
				glm::vec4(0,0,1000,1000));

			Assert::IsTrue(AreEqual(glCoreVector, glmVector));
		}

		[TestMethod]
		void Vector3MatrixMultiply()
		{
			Assert::IsTrue(true);
		}

		[TestMethod]
		void Vector3Normalize()
		{
			Vector3 glCoreVector(99, 1313, 4333);
			glCoreVector.Normalize();

			glm::vec3 glmVector(99, 1313, 4333);
			glmVector = glm::normalize(glmVector);
			
			Assert::IsTrue(AreEqual(glCoreVector, glmVector));
		}

		[TestMethod]
		void Vector3Length()
		{
			Vector3 glCoreVector(99, 1313, 4333);

			glm::vec3 glmVector(99, 1313, 4333);
			
			Assert::IsTrue(AreEqual(glCoreVector.GetLength(),
				glm::length(glmVector)));
		}

		[TestMethod]
		void Vector3Cross()
		{
			Vector3 glCoreVector = Vector3::Cross(Vector3(100, 23, -32), Vector3(342, 4, 2));

			glm::vec3 glmVector = glm::cross(glm::vec3(100, 23, -32), glm::vec3(342, 4, 2));

			Assert::IsTrue(AreEqual(glCoreVector, glmVector));
		}

		[TestMethod]
		void Vector3Dot()
		{
			float glCoreDot = Vector3::Dot(Vector3(100, 23, -32), Vector3(342, 4, 2));

			float glmDot = glm::dot(glm::vec3(100, 23, -32), glm::vec3(342, 4, 2));

			Assert::IsTrue(AreEqual(glCoreDot, glmDot));
		}

		[TestMethod]
		void Vector3MultiplyFloat()
		{
			Vector3 glCoreMatrix = Vector3(100, 23, -32) * 0.5f;

			glm::vec3 glmMatrix = glm::vec3(100, 23, -32) * 0.5f;
			
			Assert::IsTrue(AreEqual(glCoreMatrix, glmMatrix));
		}
	};
}